﻿using UnityEditor;

using UnityEngine;

namespace GameToolkit.Editor
{
    [CustomEditor(typeof(CullingCamera))]
    public class CullingCameraEditor : UnityEditor.Editor
    {
        CullingBounds mRaycast;
        GUIContent mRaycastName;
        GUIStyle mRaycastStyle;

        bool mHasMouseDown;

        //void SetRaycast(CullingBounds bounding)
        //{
        //    if (mRaycast != bounding)
        //    {
        //        mRaycast = bounding;
        //        if (mRaycastName == null)
        //            mRaycastName = new GUIContent(EditorGUIUtility.IconContent("GameObject Icon"));
        //        if (bounding != null)
        //            mRaycastName.text = bounding.name;
        //        if(mRaycastStyle == null)
        //        {
        //            mRaycastStyle = new GUIStyle(DevilEditorUtility.NormalStyle("label"));//"ol miniping"));
        //            //mRaycastStyle.stretchHeight = false;
        //            mRaycastStyle.fixedHeight = 20;
        //            mRaycastStyle.normal.textColor = Color.yellow;
        //            mRaycastStyle.alignment = TextAnchor.MiddleCenter;
        //        }
        //    }
        //}

        private void OnEnable()
        {
            mHasMouseDown = false;
        }

        private void OnDisable()
        {
            mHasMouseDown = false;
        }

        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();
            var cullcam = target as CullingCamera;
            EditorGUILayout.LabelField("Bounds Count", cullcam.CullLength.ToString());

            //mDebuging = EditorGUILayout.Foldout(mDebuging, "Debug Culling Bounds", true);
            //DebugCamera.debuging = QuickGUI.BeginGroup("Debug Culling Bounds", DebugCamera.debuging);
            //if (DebugCamera.debuging)
            //{
            //    EditorGUI.indentLevel++;
            //    EditorGUILayout.LabelField("Bounds Count", cullcam.CullLength.ToString());
            //    DebugCamera.debugPreCullAction = EditorGUILayout.Toggle("Debug PreCull Action", DebugCamera.debugPreCullAction);
            //    DebugCamera.debugCullBounding = EditorGUILayout.Toggle("Debug Cull Bounding", DebugCamera.debugCullBounding);
            //    DebugCamera.debugCullDistance = EditorGUILayout.IntSlider("Debug Cull Distance", DebugCamera.debugCullDistance, 0, 5);
            //    DebugCamera.handleSize = EditorGUILayout.Slider("Debug Handle Size", DebugCamera.handleSize, 0.1f, 1f);
            //    DebugCamera.debugSelectBounding = EditorGUILayout.Toggle("Bouding Selectable", DebugCamera.debugSelectBounding);
            //    if (DebugCamera.debugSelectBounding)
            //        EditorGUILayout.HelpBox("当鼠标悬停于裁剪对象上时，按下【A/D】切换重叠对象，【SPACE】选中目标", MessageType.Info, true);
            //    EditorGUI.indentLevel--;
            //}
            //QuickGUI.EndGroup();
        }

        bool IsVaild(ICullingBounds bound)
        {
            if (bound == null)
                return false;
            if (GlobalUtil.IsTypeInheritedFrom(bound.GetType(), typeof(Object), true))
                return ((Object)bound) != null;
            return true;
        }

        private void OnSceneGUI()
        {
            var cam = target as CullingCamera;
            if (cam == null)
                return;
            if (Event.current.type == EventType.MouseDown)
                mHasMouseDown = true;
            else if (Event.current.type == EventType.MouseUp)
                mHasMouseDown = false;
#if UNITY_2021_1_OR_NEWER
            var stage = UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage();
#else
            var stage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage();
#endif
            if (stage != null)
            {
                DebugCamera.BeginRaycast(Vector3.zero);
                DebugCamera.EndRaycast();
                return;
            }
            if(mRaycastStyle == null)
            {
                mRaycastStyle = new GUIStyle(DevilEditorUtility.NormalStyle("box"));
                mRaycastStyle.normal.textColor = Color.yellow;
                mRaycastStyle.richText = false;
            }
            var scan = SceneView.currentDrawingSceneView.camera;
            var ray = DevilEditorUtility.GetSceneViewMouseRay();
            ray.origin += ray.direction * 0.5f;
            //// ---- debug -----
            var vp = GizmosUtil.GetWorldToScreenMatrix(scan, false);// scan.projectionMatrix * scan.worldToCameraMatrix;
            var pv = vp.inverse;
            //var mpos = vp.MultiplyPoint(ray.origin);
            //Handles.Label(scan.transform.position + scan.transform.forward * 10, mpos.ToString());
            //// ----------------

            cam.ValidateCullingBounds(scan, ray, DebugCamera.debugSelectBounding && Vector3.Dot(ray.direction, scan.transform.forward) > 0, DebugCamera.handleSize);
            if(DebugCamera.debugSelectBounding && DebugCamera.SelectedBounds != null)
            {
                //var pos = ray.origin + scan.up * HandleUtility.GetHandleSize(ray.origin) * 0.5f;// DebugCamera.SelectedBounds.Bounding.position;
                var lst = DebugCamera.RaycastsList;
                var selected = lst.SelectedRaycast;
                if (!mHasMouseDown && IsVaild(selected))
                {
                    var str = string.Format("{0}\n<{1}/{2}>", ((ICullingBoundsDebug)selected).Title, lst.SelectedIndex + 1, lst.Raycasts.Count);
                    var pos = selected.Bounding.position;
                    var spos = vp.MultiplyPoint(pos);// scan.WorldToScreenPoint(pos);
                    if (spos.x < 100)
                        spos.x = 100;
                    else if (spos.x > scan.pixelWidth - 100)
                        spos.x = scan.pixelWidth - 100;

                    if (spos.y < 50)
                        spos.y = 50;
                    else if (spos.y > scan.pixelHeight - 50)
                        spos.y = scan.pixelHeight - 50;
                    pos = pv.MultiplyPoint(spos);// scan.ScreenToWorldPoint(spos);

                    Handles.Label(pos, str, mRaycastStyle);

                    if (Event.current.type == EventType.KeyDown)
                    {
                        if (Event.current.keyCode == KeyCode.A)
                        {
                            Event.current.Use();
                            lst.SelectNext(-1);
                        }
                        else if (Event.current.keyCode == KeyCode.D)
                        {
                            Event.current.Use();
                            lst.SelectNext(1);
                        }
                        else if (Event.current.keyCode == KeyCode.Space)
                        {
                            Event.current.Use();
                            ((ICullingBoundsDebug)lst.SelectedRaycast).Select();
                        }
                    }
                }

            }

            if (DebugCamera.debugSelectBounding)
                SceneView.currentDrawingSceneView.Repaint();

        }

//#if UNITY_2019_1_OR_NEWER
//        [SettingsProvider]
//        static SettingsProvider Settings()
//        {
//            return new CullingCameraSettings("Devil Framework/Culling Camera", SettingsScope.User);
//        }

//        class CullingCameraSettings : SettingsProvider
//        {
//            public CullingCameraSettings(string path, SettingsScope scopes) : base(path, scopes)
//            {
//            }

//            public override void OnGUI(string searchContext)
//            {
//                OnPreference();
//            }
//        }
//#else
//        [PreferenceItem("Devil Framework/Culling Camera")]
//#endif

//        static void OnPreference()
//        {
//            //DebugCamera.debuging = QuickGUI.BeginGroup("Debug Culling Bounds", DebugCamera.debuging);
//            DebugCamera.debuging = EditorGUILayout.Toggle("Debug Culling Bounds", DebugCamera.debuging);
//            EditorGUI.indentLevel++;
//            EditorGUI.BeginDisabledGroup(!DebugCamera.debuging);
//            //if (DebugCamera.debuging)
//            //{
//            //EditorGUILayout.LabelField("Bounds Count", cullcam.CullLength.ToString());
//            DebugCamera.debugPreCullAction = EditorGUILayout.Toggle("Debug PreCull Action", DebugCamera.debugPreCullAction);
//            DebugCamera.debugCullBounding = EditorGUILayout.Toggle("Debug Cull Bounding", DebugCamera.debugCullBounding);
//            DebugCamera.debugCullDistance = EditorGUILayout.IntSlider("Debug Cull Distance", DebugCamera.debugCullDistance, 0, 5);
//            DebugCamera.handleSize = EditorGUILayout.Slider("Debug Handle Size", DebugCamera.handleSize, 0.1f, 1f);
//            DebugCamera.debugSelectBounding = EditorGUILayout.Toggle("Bouding Selectable", DebugCamera.debugSelectBounding);
//            if (DebugCamera.debugSelectBounding)
//                EditorGUILayout.HelpBox("当鼠标悬停于裁剪对象上时，按下【A/D】切换重叠对象，【SPACE】选中目标", MessageType.Info, true);
//            //}
//            EditorGUI.EndDisabledGroup();
//            EditorGUI.indentLevel--;
//            //QuickGUI.EndGroup();
//        }
    }
}